; 抛出异常
; 中断过程 (中断向量表 在内存中的位置：0000:0000 ~ 0000:03FF)
; 1、获取中断标志位
; 2、标志位入栈（pushf） 2
; 3、将标志位的第八位TF（跟踪标志为）和第九位IF（中断标志）设置为0
; 4、push cs 2
; 5、push ip 2
; 6、计算 CS = N*4 + 2 IP = N*4
; iret pop ip pop cs  popf
; movsb指令用于把字节从ds:si 搬到es:di；rep是repeat的意思，
; rep movsb 就是多次搬运。搬运前先把字符串的长度存在cx寄存器中，
; 然后重复的次数就是cx寄存器所存数据的值。
;


assume cs:code, ds:data, ss:stack

data segment
    db 1, 0
    db 'divide error, Divisor cannot be 0', 0
data ends

stack segment stack

    db 64 dup(0)
stack ends

code segment

start:
    mov ax, stack

    mov ss, ax

    mov sp, 64

    call initReg

    call messageToMemoey

    call divide

    mov ax, 4c00H

    int 21H

    ret

divide:

    mov al, ds:[0]

    mov bl, ds:[1]

    mov cx, 0

    mov cl, 0

    cmp cl, bl

    je over

    div bl

    ret

over:
    mov word ptr es:[0 * 4], OFFSET exceptionHandling    

    mov es:[0 * 4 + 2], cs

    int 0   ; 0 号中断 除法溢出

    mov ax, 4c00H

    int 21H

    ret

exceptionHandling:

    call displayError

    mov ax, 4c00H

    int 21H
    ret
messageToMemoey: 

    mov cx, OFFSET strEnd - strStart
    mov si, 2

    mov ax, 0

    mov es, ax

    mov di, 7E00H

    cld

    rep movsb 

    ret
; =============================
; 异常处理
; =============================
displayError:

    push ds

    push es

    mov ax, 0

    mov ds, ax

    mov ax, 0b800H

    mov es, ax

    mov ax, 0

    mov si, 7E00H

    mov cx, OFFSET strEnd - strStart

    mov bp, 160*20 + 40
show:
    mov al, ds:[si]

    mov es:[bp], al

    inc bp

    mov byte ptr es:[bp], 4

    inc bp 

    inc si

    loop show

    pop es

    pop ds

    ret

initReg:

    mov ax, data

    mov ds, ax

    mov ax, 0

    mov es, ax

    mov si, 0

    mov di, 0

    ret

strStart:
    db 'divide error, Divisor cannot be 0', 0
strEnd: 
    nop

code ends

end start